package org.game.obj;

import akka.actor.typed.Behavior;
import akka.actor.typed.javadsl.ActorContext;
import akka.actor.typed.javadsl.Behaviors;
import akka.actor.typed.javadsl.ReceiveBuilder;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.common.akka.actor.BaseActor;
import org.common.akka.message.BaseMsg;
import org.common.akka.message.ClientUpMsg;
import org.common.akka.message.RoleLoginMsg;
import org.common.dispatcher.ProtoDispatcher;
import org.common.mongo.MongoService;
import org.common.mongo.collection.RoleCollection;
import org.common.mongo.collection.SimpleRoleCollection;
import org.common.netty.Pack;
import org.common.netty.PackCodec;
import org.common.utils.SpringUtils;
import org.protobuf.InnerServerMsg;
import org.protobuf.ProtoEnumMsg;

import java.lang.reflect.InvocationTargetException;


/**
 * 角色Actor
 */
@Slf4j
public class RoleActor extends BaseActor {

    private final RoleContext rc;


    public RoleContext getRc() {
        return rc;
    }

    public RoleActor(ActorContext<BaseMsg> context, SimpleRoleCollection simpleRoleCollection, Channel channel) {
        super(context);
        this.rc = new RoleContext();
        this.rc.setSimpleRoleCollection(simpleRoleCollection);
        this.rc.setAccountId(simpleRoleCollection.getAccountId());
        this.rc.setRoleId(simpleRoleCollection.getRoleId());
        this.rc.setChannel(channel);
    }

    /**
     * 生成一个RoleActor
     */
    public static Behavior<BaseMsg> create(SimpleRoleCollection simpleRoleCollection, Channel channel) {
        return Behaviors.setup(context -> new RoleActor(context, simpleRoleCollection, channel));
    }

    @Override
    protected void onCreateReceive(ReceiveBuilder<BaseMsg> builder) {
        builder.onMessage(ClientUpMsg.class, this::onClientUpMsg);
        builder.onMessage(RoleLoginMsg.class, this::onRoleLoginMsg);
    }

    /**
     * 角色登录信息
     * 进行角色数据初始化
     */
    private Behavior<BaseMsg> onRoleLoginMsg(RoleLoginMsg msg) {
        MongoService mongoService = SpringUtils.getBean(MongoService.class);
        RoleCollection roleCollection = mongoService.findById(rc.getRoleId(), RoleCollection.class);
        if (roleCollection == null) {
            // 没有角色数据，创建一个
            roleCollection = new RoleCollection();
            roleCollection.setRoleId(msg.getRoleId());
            mongoService.insert(roleCollection);
        }
        rc.initRoleContext(roleCollection);
        // 返回给Login
        InnerServerMsg.G2LRoleLogin.Builder builder = InnerServerMsg.G2LRoleLogin.newBuilder();
        builder.setRoleId(rc.getRoleId());
        builder.setAccountId(rc.getAccountId());
        rc.getChannel().writeAndFlush(PackCodec.encode(ProtoEnumMsg.CMD.ID.NOTIFY_GAME_ROLE_LOGIN_VALUE, builder.build().toByteArray()));
        log.info("roleActor，角色登录 roleId = {}", rc.getRoleId());
        return this;
    }

    /**
     * 客户端上行协议
     */
    private Behavior<BaseMsg> onClientUpMsg(ClientUpMsg msg) {
        ProtoDispatcher dispatcher = SpringUtils.getBean(ProtoDispatcher.class);
        byte[] data = msg.getData();
        Pack decode = PackCodec.decode(data);
        Pack ret;
        try {
            ret = dispatcher.dispatch(decode.getCmdId(), decode.getData(), getRc());
        } catch (InvocationTargetException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        if (ret != null) {
            // 回包给客户端
            rc.push(ret);
        }
        return this;
    }

}
